home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / gettext / intl / printf-parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-03-05  |  12.2 KB  |  545 lines

  1. /* Formatted output to strings.
  2.    Copyright (C) 1999-2000, 2002-2003, 2006 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify it
  5.    under the terms of the GNU Library General Public License as published
  6.    by the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.    Library General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU Library General Public
  15.    License along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  17.    USA.  */
  18.  
  19. #include <config.h>
  20.  
  21. /* Specification.  */
  22. #if WIDE_CHAR_VERSION
  23. # include "wprintf-parse.h"
  24. #else
  25. # include "printf-parse.h"
  26. #endif
  27.  
  28. /* Get size_t, NULL.  */
  29. #include <stddef.h>
  30.  
  31. /* Get intmax_t.  */
  32. #if HAVE_STDINT_H_WITH_UINTMAX
  33. # include <stdint.h>
  34. #endif
  35. #if HAVE_INTTYPES_H_WITH_UINTMAX
  36. # include <inttypes.h>
  37. #endif
  38.  
  39. /* malloc(), realloc(), free().  */
  40. #include <stdlib.h>
  41.  
  42. /* Checked size_t computations.  */
  43. #include "xsize.h"
  44.  
  45. #if WIDE_CHAR_VERSION
  46. # define PRINTF_PARSE wprintf_parse
  47. # define CHAR_T wchar_t
  48. # define DIRECTIVE wchar_t_directive
  49. # define DIRECTIVES wchar_t_directives
  50. #else
  51. # define PRINTF_PARSE printf_parse
  52. # define CHAR_T char
  53. # define DIRECTIVE char_directive
  54. # define DIRECTIVES char_directives
  55. #endif
  56.  
  57. #ifdef STATIC
  58. STATIC
  59. #endif
  60. int
  61. PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
  62. {
  63.   const CHAR_T *cp = format;        /* pointer into format */
  64.   size_t arg_posn = 0;        /* number of regular arguments consumed */
  65.   size_t d_allocated;            /* allocated elements of d->dir */
  66.   size_t a_allocated;            /* allocated elements of a->arg */
  67.   size_t max_width_length = 0;
  68.   size_t max_precision_length = 0;
  69.  
  70.   d->count = 0;
  71.   d_allocated = 1;
  72.   d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
  73.   if (d->dir == NULL)
  74.     /* Out of memory.  */
  75.     return -1;
  76.  
  77.   a->count = 0;
  78.   a_allocated = 0;
  79.   a->arg = NULL;
  80.  
  81. #define REGISTER_ARG(_index_,_type_) \
  82.   {                                    \
  83.     size_t n = (_index_);                        \
  84.     if (n >= a_allocated)                        \
  85.       {                                    \
  86.     size_t memory_size;                        \
  87.     argument *memory;                        \
  88.                                     \
  89.     a_allocated = xtimes (a_allocated, 2);                \
  90.     if (a_allocated <= n)                        \
  91.       a_allocated = xsum (n, 1);                    \
  92.     memory_size = xtimes (a_allocated, sizeof (argument));        \
  93.     if (size_overflow_p (memory_size))                \
  94.       /* Overflow, would lead to out of memory.  */            \
  95.       goto error;                            \
  96.     memory = (a->arg                        \
  97.           ? realloc (a->arg, memory_size)            \
  98.           : malloc (memory_size));                \
  99.     if (memory == NULL)                        \
  100.       /* Out of memory.  */                        \
  101.       goto error;                            \
  102.     a->arg = memory;                        \
  103.       }                                    \
  104.     while (a->count <= n)                        \
  105.       a->arg[a->count++].type = TYPE_NONE;                \
  106.     if (a->arg[n].type == TYPE_NONE)                    \
  107.       a->arg[n].type = (_type_);                    \
  108.     else if (a->arg[n].type != (_type_))                \
  109.       /* Ambiguous type for positional argument.  */            \
  110.       goto error;                            \
  111.   }
  112.  
  113.   while (*cp != '\0')
  114.     {
  115.       CHAR_T c = *cp++;
  116.       if (c == '%')
  117.     {
  118.       size_t arg_index = ARG_NONE;
  119.       DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
  120.  
  121.       /* Initialize the next directive.  */
  122.       dp->dir_start = cp - 1;
  123.       dp->flags = 0;
  124.       dp->width_start = NULL;
  125.       dp->width_end = NULL;
  126.       dp->width_arg_index = ARG_NONE;
  127.       dp->precision_start = NULL;
  128.       dp->precision_end = NULL;
  129.       dp->precision_arg_index = ARG_NONE;
  130.       dp->arg_index = ARG_NONE;
  131.  
  132.       /* Test for positional argument.  */
  133.       if (*cp >= '0' && *cp <= '9')
  134.         {
  135.           const CHAR_T *np;
  136.  
  137.           for (np = cp; *np >= '0' && *np <= '9'; np++)
  138.         ;
  139.           if (*np == '$')
  140.         {
  141.           size_t n = 0;
  142.  
  143.           for (np = cp; *np >= '0' && *np <= '9'; np++)
  144.             n = xsum (xtimes (n, 10), *np - '0');
  145.           if (n == 0)
  146.             /* Positional argument 0.  */
  147.             goto error;
  148.           if (size_overflow_p (n))
  149.             /* n too large, would lead to out of memory later.  */
  150.             goto error;
  151.           arg_index = n - 1;
  152.           cp = np + 1;
  153.         }
  154.         }
  155.  
  156.       /* Read the flags.  */
  157.       for (;;)
  158.         {
  159.           if (*cp == '\'')
  160.         {
  161.           dp->flags |= FLAG_GROUP;
  162.           cp++;
  163.         }
  164.           else if (*cp == '-')
  165.         {
  166.           dp->flags |= FLAG_LEFT;
  167.           cp++;
  168.         }
  169.           else if (*cp == '+')
  170.         {
  171.           dp->flags |= FLAG_SHOWSIGN;
  172.           cp++;
  173.         }
  174.           else if (*cp == ' ')
  175.         {
  176.           dp->flags |= FLAG_SPACE;
  177.           cp++;
  178.         }
  179.           else if (*cp == '#')
  180.         {
  181.           dp->flags |= FLAG_ALT;
  182.           cp++;
  183.         }
  184.           else if (*cp == '0')
  185.         {
  186.           dp->flags |= FLAG_ZERO;
  187.           cp++;
  188.         }
  189.           else
  190.         break;
  191.         }
  192.  
  193.       /* Parse the field width.  */
  194.       if (*cp == '*')
  195.         {
  196.           dp->width_start = cp;
  197.           cp++;
  198.           dp->width_end = cp;
  199.           if (max_width_length < 1)
  200.         max_width_length = 1;
  201.  
  202.           /* Test for positional argument.  */
  203.           if (*cp >= '0' && *cp <= '9')
  204.         {
  205.           const CHAR_T *np;
  206.  
  207.           for (np = cp; *np >= '0' && *np <= '9'; np++)
  208.             ;
  209.           if (*np == '$')
  210.             {
  211.               size_t n = 0;
  212.  
  213.               for (np = cp; *np >= '0' && *np <= '9'; np++)
  214.             n = xsum (xtimes (n, 10), *np - '0');
  215.               if (n == 0)
  216.             /* Positional argument 0.  */
  217.             goto error;
  218.               if (size_overflow_p (n))
  219.             /* n too large, would lead to out of memory later.  */
  220.             goto error;
  221.               dp->width_arg_index = n - 1;
  222.               cp = np + 1;
  223.             }
  224.         }
  225.           if (dp->width_arg_index == ARG_NONE)
  226.         {
  227.           dp->width_arg_index = arg_posn++;
  228.           if (dp->width_arg_index == ARG_NONE)
  229.             /* arg_posn wrapped around.  */
  230.             goto error;
  231.         }
  232.           REGISTER_ARG (dp->width_arg_index, TYPE_INT);
  233.         }
  234.       else if (*cp >= '0' && *cp <= '9')
  235.         {
  236.           size_t width_length;
  237.  
  238.           dp->width_start = cp;
  239.           for (; *cp >= '0' && *cp <= '9'; cp++)
  240.         ;
  241.           dp->width_end = cp;
  242.           width_length = dp->width_end - dp->width_start;
  243.           if (max_width_length < width_length)
  244.         max_width_length = width_length;
  245.         }
  246.  
  247.       /* Parse the precision.  */
  248.       if (*cp == '.')
  249.         {
  250.           cp++;
  251.           if (*cp == '*')
  252.         {
  253.           dp->precision_start = cp - 1;
  254.           cp++;
  255.           dp->precision_end = cp;
  256.           if (max_precision_length < 2)
  257.             max_precision_length = 2;
  258.  
  259.           /* Test for positional argument.  */
  260.           if (*cp >= '0' && *cp <= '9')
  261.             {
  262.               const CHAR_T *np;
  263.  
  264.               for (np = cp; *np >= '0' && *np <= '9'; np++)
  265.             ;
  266.               if (*np == '$')
  267.             {
  268.               size_t n = 0;
  269.  
  270.               for (np = cp; *np >= '0' && *np <= '9'; np++)
  271.                 n = xsum (xtimes (n, 10), *np - '0');
  272.               if (n == 0)
  273.                 /* Positional argument 0.  */
  274.                 goto error;
  275.               if (size_overflow_p (n))
  276.                 /* n too large, would lead to out of memory
  277.                    later.  */
  278.                 goto error;
  279.               dp->precision_arg_index = n - 1;
  280.               cp = np + 1;
  281.             }
  282.             }
  283.           if (dp->precision_arg_index == ARG_NONE)
  284.             {
  285.               dp->precision_arg_index = arg_posn++;
  286.               if (dp->precision_arg_index == ARG_NONE)
  287.             /* arg_posn wrapped around.  */
  288.             goto error;
  289.             }
  290.           REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
  291.         }
  292.           else
  293.         {
  294.           size_t precision_length;
  295.  
  296.           dp->precision_start = cp - 1;
  297.           for (; *cp >= '0' && *cp <= '9'; cp++)
  298.             ;
  299.           dp->precision_end = cp;
  300.           precision_length = dp->precision_end - dp->precision_start;
  301.           if (max_precision_length < precision_length)
  302.             max_precision_length = precision_length;
  303.         }
  304.         }
  305.  
  306.       {
  307.         arg_type type;
  308.  
  309.         /* Parse argument type/size specifiers.  */
  310.         {
  311.           int flags = 0;
  312.  
  313.           for (;;)
  314.         {
  315.           if (*cp == 'h')
  316.             {
  317.               flags |= (1 << (flags & 1));
  318.               cp++;
  319.             }
  320.           else if (*cp == 'L')
  321.             {
  322.               flags |= 4;
  323.               cp++;
  324.             }
  325.           else if (*cp == 'l')
  326.             {
  327.               flags += 8;
  328.               cp++;
  329.             }
  330. #ifdef HAVE_INTMAX_T
  331.           else if (*cp == 'j')
  332.             {
  333.               if (sizeof (intmax_t) > sizeof (long))
  334.             {
  335.               /* intmax_t = long long */
  336.               flags += 16;
  337.             }
  338.               else if (sizeof (intmax_t) > sizeof (int))
  339.             {
  340.               /* intmax_t = long */
  341.               flags += 8;
  342.             }
  343.               cp++;
  344.             }
  345. #endif
  346.           else if (*cp == 'z' || *cp == 'Z')
  347.             {
  348.               /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
  349.              because the warning facility in gcc-2.95.2 understands
  350.              only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
  351.               if (sizeof (size_t) > sizeof (long))
  352.             {
  353.               /* size_t = long long */
  354.               flags += 16;
  355.             }
  356.               else if (sizeof (size_t) > sizeof (int))
  357.             {
  358.               /* size_t = long */
  359.               flags += 8;
  360.             }
  361.               cp++;
  362.             }
  363.           else if (*cp == 't')
  364.             {
  365.               if (sizeof (ptrdiff_t) > sizeof (long))
  366.             {
  367.               /* ptrdiff_t = long long */
  368.               flags += 16;
  369.             }
  370.               else if (sizeof (ptrdiff_t) > sizeof (int))
  371.             {
  372.               /* ptrdiff_t = long */
  373.               flags += 8;
  374.             }
  375.               cp++;
  376.             }
  377.           else
  378.             break;
  379.         }
  380.  
  381.           /* Read the conversion character.  */
  382.           c = *cp++;
  383.           switch (c)
  384.         {
  385.         case 'd': case 'i':
  386. #ifdef HAVE_LONG_LONG_INT
  387.           /* If 'long long' exists and is larger than 'long':  */
  388.           if (flags >= 16 || (flags & 4))
  389.             type = TYPE_LONGLONGINT;
  390.           else
  391. #endif
  392.           /* If 'long long' exists and is the same as 'long', we parse
  393.              "lld" into TYPE_LONGINT.  */
  394.           if (flags >= 8)
  395.             type = TYPE_LONGINT;
  396.           else if (flags & 2)
  397.             type = TYPE_SCHAR;
  398.           else if (flags & 1)
  399.             type = TYPE_SHORT;
  400.           else
  401.             type = TYPE_INT;
  402.           break;
  403.         case 'o': case 'u': case 'x': case 'X':
  404. #ifdef HAVE_LONG_LONG_INT
  405.           /* If 'long long' exists and is larger than 'long':  */
  406.           if (flags >= 16 || (flags & 4))
  407.             type = TYPE_ULONGLONGINT;
  408.           else
  409. #endif
  410.           /* If 'unsigned long long' exists and is the same as
  411.              'unsigned long', we parse "llu" into TYPE_ULONGINT.  */
  412.           if (flags >= 8)
  413.             type = TYPE_ULONGINT;
  414.           else if (flags & 2)
  415.             type = TYPE_UCHAR;
  416.           else if (flags & 1)
  417.             type = TYPE_USHORT;
  418.           else
  419.             type = TYPE_UINT;
  420.           break;
  421.         case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
  422.         case 'a': case 'A':
  423. #ifdef HAVE_LONG_DOUBLE
  424.           if (flags >= 16 || (flags & 4))
  425.             type = TYPE_LONGDOUBLE;
  426.           else
  427. #endif
  428.           type = TYPE_DOUBLE;
  429.           break;
  430.         case 'c':
  431.           if (flags >= 8)
  432. #ifdef HAVE_WINT_T
  433.             type = TYPE_WIDE_CHAR;
  434. #else
  435.             goto error;
  436. #endif
  437.           else
  438.             type = TYPE_CHAR;
  439.           break;
  440. #ifdef HAVE_WINT_T
  441.         case 'C':
  442.           type = TYPE_WIDE_CHAR;
  443.           c = 'c';
  444.           break;
  445. #endif
  446.         case 's':
  447.           if (flags >= 8)
  448. #ifdef HAVE_WCHAR_T
  449.             type = TYPE_WIDE_STRING;
  450. #else
  451.             goto error;
  452. #endif
  453.           else
  454.             type = TYPE_STRING;
  455.           break;
  456. #ifdef HAVE_WCHAR_T
  457.         case 'S':
  458.           type = TYPE_WIDE_STRING;
  459.           c = 's';
  460.           break;
  461. #endif
  462.         case 'p':
  463.           type = TYPE_POINTER;
  464.           break;
  465.         case 'n':
  466. #ifdef HAVE_LONG_LONG_INT
  467.           /* If 'long long' exists and is larger than 'long':  */
  468.           if (flags >= 16 || (flags & 4))
  469.             type = TYPE_COUNT_LONGLONGINT_POINTER;
  470.           else
  471. #endif
  472.           /* If 'long long' exists and is the same as 'long', we parse
  473.              "lln" into TYPE_COUNT_LONGINT_POINTER.  */
  474.           if (flags >= 8)
  475.             type = TYPE_COUNT_LONGINT_POINTER;
  476.           else if (flags & 2)
  477.             type = TYPE_COUNT_SCHAR_POINTER;
  478.           else if (flags & 1)
  479.             type = TYPE_COUNT_SHORT_POINTER;
  480.           else
  481.             type = TYPE_COUNT_INT_POINTER;
  482.           break;
  483.         case '%':
  484.           type = TYPE_NONE;
  485.           break;
  486.         default:
  487.           /* Unknown conversion character.  */
  488.           goto error;
  489.         }
  490.         }
  491.  
  492.         if (type != TYPE_NONE)
  493.           {
  494.         dp->arg_index = arg_index;
  495.         if (dp->arg_index == ARG_NONE)
  496.           {
  497.             dp->arg_index = arg_posn++;
  498.             if (dp->arg_index == ARG_NONE)
  499.               /* arg_posn wrapped around.  */
  500.               goto error;
  501.           }
  502.         REGISTER_ARG (dp->arg_index, type);
  503.           }
  504.         dp->conversion = c;
  505.         dp->dir_end = cp;
  506.       }
  507.  
  508.       d->count++;
  509.       if (d->count >= d_allocated)
  510.         {
  511.           size_t memory_size;
  512.           DIRECTIVE *memory;
  513.  
  514.           d_allocated = xtimes (d_allocated, 2);
  515.           memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
  516.           if (size_overflow_p (memory_size))
  517.         /* Overflow, would lead to out of memory.  */
  518.         goto error;
  519.           memory = realloc (d->dir, memory_size);
  520.           if (memory == NULL)
  521.         /* Out of memory.  */
  522.         goto error;
  523.           d->dir = memory;
  524.         }
  525.     }
  526.     }
  527.   d->dir[d->count].dir_start = cp;
  528.  
  529.   d->max_width_length = max_width_length;
  530.   d->max_precision_length = max_precision_length;
  531.   return 0;
  532.  
  533. error:
  534.   if (a->arg)
  535.     free (a->arg);
  536.   if (d->dir)
  537.     free (d->dir);
  538.   return -1;
  539. }
  540.  
  541. #undef DIRECTIVES
  542. #undef DIRECTIVE
  543. #undef CHAR_T
  544. #undef PRINTF_PARSE
  545.